﻿#region Copyright Notice
// 
// 
//  
//  Copyright (c) 2009-2011 Anindya Chatterjee
//  
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//  
//      http://www.apache.org/licenses/LICENSE-2.0
//  
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// 
// 
#endregion
using System;
using System.Collections.Generic;
using System.Threading;
using AbstractClass;
using AbstractClass.Threading.Tasks;
using NUnit.Framework;

namespace QuasarTest.Core
{
    [TestFixture]
    public class JobEngineTest
    {
        #region Setup/Teardown

        [SetUp]
        public void Init()
        {
            _task1 = new Load<int, TestResult>(Run, 1);
            _task2 = new Load<int, TestResult>(Run, 2);
            _task3 = new Load<int, TestResult>(Run, 3);
            _task4 = new Load<int, TestResult>(Run, 4);

            _task5 = new Load<int, float, TestResult>(Run, 5, 5.0f);
            _task6 = new Load<int, float, TestResult>(Run, 6, 6.0f);
            _task7 = new Load<int, float, TestResult>(Run, 7, 7.0f);

            _action1 = new Work(RunVoid);
            _action2 = new Work<int>(RunVoid, 2);
            _action3 = new Work<int>(RunVoid, 3);
            _action4 = new Work<float>(RunVoid, 4.0f);
        }

        #endregion

        private Job<TestResult> _task1, _task2, _task3, _task4, _task5, _task6, _task7;
        private Work _action1;
        private Work<int> _action2, _action3;
        private Work<float> _action4;

        private static void JobCompleted(object sender, JobCompletedEventArgs<TestResult> e)
        {
            Console.WriteLine(e.Result.Data);
        }

        private static void ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            Console.WriteLine("Progress = {0}", e.ProgressPercentage);
            //if(e.ProgressPercentage > 50)
            //    ((JobEngine<TestResult>)sender).Cancel();
        }

        private static void ExecutionStarted(object sender, EventArgs e)
        {
            Console.WriteLine("Job execution started");
        }

        private static void ExecutionEnded(object sender, EventArgs e)
        {
            Console.WriteLine("Job Execution ended");
        }

        private static void ExecutionCancelled(object sender, EventArgs e)
        {
            Console.WriteLine("Execution cancelled");
        }

        private static TestResult Run(int i)
        {
            var data = new TestResult {StartTime = DateTime.Now};
            string result = string.Format("Task {0} started at {1}", i, data.StartTime);
            Thread.Sleep(1000 * i);
            data.EndTime = DateTime.Now;
            result += string.Format(" and ended at {0}", data.EndTime);
            data.Data = result;
            return data;
        }

        private static TestResult Run(int i, float j)
        {
            var data = new TestResult {StartTime = DateTime.Now};
            string result = string.Format("Task {0} started at {1}", j, data.StartTime);
            Thread.Sleep(1000 * i);
            data.EndTime = DateTime.Now;
            result += string.Format(" and ended at {0}", data.EndTime);
            data.Data = result;
            return data;
        }

        private static void RunVoid()
        {
            DateTime time = DateTime.Now;
            Thread.Sleep(1000);
            Console.WriteLine("This Action has started at {0} and ended at {1}", time, DateTime.Now);
        }

        private static void RunVoid(int i)
        {
            DateTime time = DateTime.Now;
            Thread.Sleep(1000 * i);
            Console.WriteLine("Action {0} has started at {1} and ended at {2}", i, time, DateTime.Now);
        }

        private static void RunVoid(float i)
        {
            DateTime time = DateTime.Now;
            Thread.Sleep(1000);
            Console.WriteLine("Action {0} has started at {1} and ended at {2}", i, time, DateTime.Now);
        }

        [Test]
        public void TestGetResults()
        {
            JobEngine<TestResult> jobEngine = _task1 - _task2 + _task3 + _task4 - _task5 - _task6 + _task7;
            jobEngine.JobCompleted += JobCompleted;
            jobEngine.Start();

            Dictionary<string, TestResult> results = jobEngine.GetResults();

            Assert.AreEqual(results[_task1.JobId].StartTime.ToString("hh:mm:ss tt"),
                            results[_task2.JobId].StartTime.ToString("hh:mm:ss tt"));
            Assert.AreEqual(results[_task2.JobId].EndTime.ToString("hh:mm:ss tt"),
                            results[_task3.JobId].StartTime.ToString("hh:mm:ss tt"));
            Assert.AreEqual(results[_task3.JobId].EndTime.ToString("hh:mm:ss tt"),
                            results[_task4.JobId].StartTime.ToString("hh:mm:ss tt"));
            Assert.AreEqual(results[_task4.JobId].StartTime.ToString("hh:mm:ss tt"),
                            results[_task5.JobId].StartTime.ToString("hh:mm:ss tt"));
            Assert.AreEqual(results[_task4.JobId].StartTime.ToString("hh:mm:ss tt"),
                            results[_task6.JobId].StartTime.ToString("hh:mm:ss tt"));
            Assert.AreEqual(results[_task6.JobId].EndTime.ToString("hh:mm:ss tt"),
                            results[_task7.JobId].StartTime.ToString("hh:mm:ss tt"));
        }

        [Test, STAThread]
        public void TestStart()
        {
            JobEngine<TestResult> jobEngine = _task1 - _task2 + _task3 + _task4 - _task5 - _task6 + _task7;
            jobEngine.JobCompleted += JobCompleted;
            jobEngine.ExecutionStarted += ExecutionStarted;
            jobEngine.ExecutionEnded += ExecutionEnded;
            jobEngine.ProgressChanged += ProgressChanged;
            jobEngine.ExecutionCancelled += ExecutionCancelled;
            jobEngine.Start();

            JobEngine<WorkCompletionStatus> engine = _action1 + _action2 - _action3 - _action4;
            engine.Start();
        }
    }
}